import tenseal as ts
from pypbc import *
from utils.masked_input import Verify_agg_sign_2, decompose_trac_w_new, Verify_sign_1, Hhash

def Tracing(args, idxs_users, pk_sign_1_s, pk_sign_2_s, pairing, G2, g2, context, len_h1_list, all_num_users, pp2, pp1):
    unhonest_participant = []

    pk_sign_1_s_trac, pk_sign_2_s_trac = [], []
    for pks in pk_sign_1_s:
        if pks != 0:
            pk_sign_1_s_trac.append(pks)

    tra_enc_w_new_s, trac_sig1_s, trac_sig2_s = [], [], []
    trac_decry_w_new_list = []
    num_user = len(idxs_users)
    for idx in range(num_user):
        str_idx = str(idx)

        filename0 = './local_BFV/local_BFV_' + str_idx + '.txt'
        with open(filename0, 'rb') as f:
            trac_local_BFV_bytes = f.read()
        f.close()
        tra_enc_w_new_s.append(trac_local_BFV_bytes)                             # 向量密文

        filename1 = './local_sig1/local_sig1_' + str_idx + '.txt'
        with open(filename1, 'r') as f1:
            trac_str_sig1_idx = f1.read()
        f1.close()
        trac_sig1_s.append(trac_str_sig1_idx)                                    # 签名1

        filename2 = './local_sig2/local_sig2_' + str_idx + '.txt'
        with open(filename2, 'r') as f2:
            trac_str_sig2_idx = f2.read()
        f2.close()

        trac_sig2_idx = Element(pairing, G2, value=trac_str_sig2_idx)
        trac_sig2_s.append(trac_sig2_idx)                                        # 签名2
    #
    # filename4 = './agg_BFV/agg_BFV_w_new' + '.txt'
    # with open(filename4, 'rb') as f:
    #     agg_BFV_bytes_recover = f.read()
    # f.close()
    #
    # w_new_s_BFV = ts.bfv_vector_from(context, tra_enc_w_new_s[args.num_clients - 1])  # 反序列化
    # for i in range(args.num_clients - 1):
    #     w_new_s_BFV = w_new_s_BFV + ts.bfv_vector_from(context, tra_enc_w_new_s[i])
    #
    # # print("type(w_new_s_BFV) = ", type(w_new_s_BFV))
    # local_BFV_bytes = w_new_s_BFV.serialize()
    # # print("type(local_BFV_bytes) = ", type(local_BFV_bytes))
    # # print("type(agg_BFV_bytes_recover) = ", type(agg_BFV_bytes_recover))
    # # if w_new_s_BFV == agg_BFV_bytes_recover:
    # if local_BFV_bytes == agg_BFV_bytes_recover:
    #     print("w_new_s_BFV == agg_BFV_bytes_recover")
    # else:
    #     unhonest_participant.append("Server")
    #     print("server is malicious")

    verify_trace_2 = Verify_agg_sign_2(tra_enc_w_new_s, pairing, trac_sig1_s, pk_sign_2_s, num_user, g2, trac_sig2_s)
    print("verify_trace_2 = ", verify_trace_2)

    if verify_trace_2 == 1:
        # 解密
        for i in range(num_user):
            trac_enc_w_new_bfv = ts.bfv_vector_from(context, tra_enc_w_new_s[i])        # 反序列化
            trac_decry_w_new = trac_enc_w_new_bfv.decrypt()                             # 解密
            trac_decry_w_new_list.append(trac_decry_w_new)
        # 分解向量   wu, h1u, hvu
        decrypted_w_loc_list, h1_idx_trac_list, h1_idx_ASCII_list = [], [], []
        for idx_1, trac_decr_w_new in zip(range(len(idxs_users)), trac_decry_w_new_list):
            decrypted_w_loc, h1_idx_chr_str, h1_idx_ASCII = decompose_trac_w_new(trac_decr_w_new, idx_1, len_h1_list,
                                                                                    all_num_users)
            decrypted_w_loc_list.append(decrypted_w_loc)

            h1_idx_ASCII_list.append(h1_idx_ASCII)
            h1_idx_ele_trac = Element(pairing, G2, value=h1_idx_chr_str)
            h1_idx_trac_list.append(h1_idx_ele_trac)

        # 利用签名1进行验证
        len_hv = 130 * args.num_clients
        len_pp2 = len_hv

        for i in range(num_user):
            hv_ini = [0] * len_hv
            # 构建本地向量
            a = i * 130
            b = a + 130
            replace_indices = list(range(a, b))
            for k, j in enumerate(replace_indices):
                hv_ini[j] = h1_idx_ASCII_list[i][k]

            h2_idx_pre = Hhash(pp2, hv_ini, len_pp2, pairing)
            h2_idx_trac = Element.__mul__(h1_idx_trac_list[i], h2_idx_pre)

            sig1_s_ele_trac = Element(pairing, G2, value=trac_sig1_s[i])
            Trac_verify1 = Verify_sign_1(pairing, g2, sig1_s_ele_trac, pk_sign_1_s_trac[i], h2_idx_trac)
            # print("Trac_verify1 = ",Trac_verify1)
            if Trac_verify1 == 0:
                unhonest_participant.append(str(i))

        len_w_idx = len(decrypted_w_loc_list[0])
        # if len(unhonest_participant) == 0:
        if len(unhonest_participant) <=10:
            for i in range(num_user):
                h1_idx = Hhash(pp1, decrypted_w_loc_list[i], len_w_idx, pairing)
                if h1_idx != h1_idx_trac_list[i]:
                    unhonest_participant.append(str(i))
            if len(unhonest_participant) == 0:
                unhonest_participant.append("Server")

    # elif Verify_agg_sign_2(tra_enc_w_new_s, pairing, trac_sig1_s, pk_sign_2_s, num_user, g2, trac_sig2_s) == 0:
    else:
        unhonest_participant.append("Server")

    return unhonest_participant